#include <stdio.h>
#include<string.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <assert.h>
#include<time.h>

#define NUM 10

typedef void (*func_t)();// 函数指针
func_t handlerTask[NUM];

//样例任务
void task1()
{
  printf("task1\n");
}

void task2()
{
  printf("task2\n");
}

void task3()
{
  printf("task3\n");
}

void loadTask()
{
  memset(handlerTask, 0, sizeof(handlerTask) );
  handlerTask[0]=task1;
  handlerTask[1]=task2;
  handlerTask[2]=task3;
}

int main()
{
  srand(time(0));

  pid_t id = fork();
  assert(id != -1);
  if(id == 0)
  {
    //child
    int t = rand();
    int cnt = 10;
    while(cnt != 0)
    {
      printf("child pid:%d ppid:%d ret:%d\n", getpid(), getppid(), cnt--);
      sleep(2);

      if(t%2 == 1)
      {
        //异常退出
        int a = 1/0;
      }
    }

    //正常退出
    exit(2);
  }
  
  loadTask();

  // parent,轮询等待
  while(1)
  {
    int status = 0;
    pid_t ret = waitpid(id, &status, WNOHANG); //W NO HANG 表示非阻塞 -> 子进程没有退出，父进程检测之后立即返回
    if( ret == 0 )
    {
      //waitpid调用成功,为一次非阻塞等待
      //子进程没有退出，我的waitpid没有等待失败，仅仅检测到子进程没有退出
      printf("wait done but child is running....., parent is running other things\n");
      for(int i = 0; handlerTask[i] != 0; i++)
      {
        handlerTask[i](); //采用回调的方式，在父亲空闲的时候，执行我们的任务
      }
    }
    else if(ret == id)
    {
      //waitpid 调用成功，等待成功。并且子进程退出了
      printf("wait success, exit_signal:%d, exit_code:%d\n", (status & 0x7f), ((status>>8) & 0xff));
      break;
    }
    else 
    {
      //等待失败，waitpid调用失败
      printf("waitpid call failed!\n");    
      break;
    }
    sleep(1);
  }

  return 0;
}
